package com.caregiver.watch.business.user.service.impl;

import com.caregiver.watch.business.user.dao.UserChatMessageDao;
import com.caregiver.watch.business.user.dao.UserChatMessageReadRecordDao;
import com.caregiver.watch.business.user.dao.UserChatWindowInfoDao;
import com.caregiver.watch.business.user.model.bo.UnreadMessageCountBo;
import com.caregiver.watch.business.user.model.dto.ChatMessage;
import com.caregiver.watch.business.user.model.dto.ReadMessageParam;
import com.caregiver.watch.business.user.model.po.UserChatMessage;
import com.caregiver.watch.business.user.model.po.UserChatMessageReadRecord;
import com.caregiver.watch.business.user.model.po.UserChatWindowInfo;
import com.caregiver.watch.business.user.model.vo.ChatMessageVo;
import com.caregiver.watch.business.user.model.vo.ChatWindowVo;
import com.caregiver.watch.business.user.service.ChatService;
import com.caregiver.watch.business.care.service.CareRecipientService;
import com.caregiver.watch.business.user.utils.UserInfoUtils;
import com.caregiver.watch.common.constant.NumberConstants;
import com.caregiver.watch.common.exception.business.BusinessException;
import com.caregiver.watch.common.utils.collection.ListUtils;
import com.caregiver.watch.common.utils.page.PageUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

import static com.caregiver.watch.common.constant.NumberConstants.ONE;
import static com.caregiver.watch.common.constant.NumberConstants.ZERO;
import static com.caregiver.watch.common.utils.page.PageUtils.ORDER_BY_CREATE_TIME_DESC;

/**
 * @Description: 聊天服务
 * @Author 疆戟
 * @Date 2025/8/30 8:50
 * @Version 1.0
 */
@AllArgsConstructor
@Service
@Slf4j
public class ChatServiceImpl implements ChatService {


    private final UserChatWindowInfoDao userChatWindowInfoDao;
    private final UserChatMessageReadRecordDao userChatMessageReadRecordDao;
    private final UserChatMessageDao userChatMessageDao;
    private final CareRecipientService careRecipientService;



    @Override
    public List<ChatWindowVo> queryChatWindowList(List<Long> recipientIds) {
        if (CollectionUtils.isEmpty(recipientIds)) {
            return Collections.emptyList();
        }
        Long userId = UserInfoUtils.getUserId();
        List<UserChatWindowInfo> userChatWindowInfos = userChatWindowInfoDao.queryUserChatWindowInfoByUserAndRecipient(userId, recipientIds);
        if (CollectionUtils.isEmpty(userChatWindowInfos)) {
            return Collections.emptyList();
        }
        List<Long> chatWindowIds = ListUtils.mapDistinct(userChatWindowInfos, UserChatWindowInfo::getChatWindowId);
        Map<Long, UnreadMessageCountBo> chatWindowIdToUnreadMessageCountMapping = queryChatWindowIdToUnreadMessageCountMapping(userId, chatWindowIds);
        Map<Long, UserChatMessage> chatWindowIdToLastMessageMapping = queryChatWindowIdToLastMessageMapping(chatWindowIds);
        return ListUtils.map(userChatWindowInfos, userChatWindowInfo -> {
            UnreadMessageCountBo countBo = chatWindowIdToUnreadMessageCountMapping.get(userChatWindowInfo.getChatWindowId());
            UserChatMessage lastMessage = chatWindowIdToLastMessageMapping.get(userChatWindowInfo.getChatWindowId());
            return ChatWindowVo.build(userChatWindowInfo, countBo, lastMessage);
        });
    }

    /**
     * 查询用户聊天窗口未读消息数
     *
     * @param userId
     * @param chatWindowIds
     * @return
     */
    private Map<Long, UnreadMessageCountBo> queryChatWindowIdToUnreadMessageCountMapping(Long userId, List<Long> chatWindowIds) {
        if (CollectionUtils.isEmpty(chatWindowIds)) {
            return Collections.emptyMap();
        }
        List<UnreadMessageCountBo> unreadMessageCountBos = userChatMessageDao.countUnreadMessagesForMultipleWindows(chatWindowIds, userId);
        return ListUtils.toMap(unreadMessageCountBos, UnreadMessageCountBo::getChatWindowId, Function.identity());
    }

    /**
     * 查询聊天窗口ID到最后一条消息的映射
     *
     * @param chatWindowIds
     * @return
     */
    private Map<Long, UserChatMessage> queryChatWindowIdToLastMessageMapping(List<Long> chatWindowIds) {
        List<UserChatMessage> lastMessages = userChatMessageDao.queryLastMessages(chatWindowIds);
        return ListUtils.toMap(lastMessages, UserChatMessage::getChatWindowId, Function.identity());
    }

    @Override
    public List<ChatMessageVo> queryMessageList(Long chatWindowId, Integer pageNum, Integer pageSize) {
        if (Objects.isNull(chatWindowId)) {
            return Collections.emptyList();
        }
        return PageUtils.selectPage(pageNum, pageSize,
                () -> userChatMessageDao.selectChatMessagesByWindowId(chatWindowId),
                message -> ChatMessageVo.build(message),
                ORDER_BY_CREATE_TIME_DESC);
    }

    @Override
    public Boolean sendMessage(ChatMessage message) {
        if (Objects.isNull(message)) {
            return Boolean.FALSE;
        }
        if (StringUtils.isBlank(message.getContent())) {
            throw new BusinessException("消息内容不能为空");
        }
        if (Objects.isNull(message.getRecipientId())) {
            throw new BusinessException("被照护人不能为空");
        }
        if (Objects.isNull(message.getMessageType())) {
            throw new BusinessException("消息类型不能为空");
        }
        Long recipientId = message.getRecipientId();
        Long userId = UserInfoUtils.getUserId();
        // 校验被照护人是否存在
        if (BooleanUtils.isNotTrue(careRecipientService.checkUserExist(userId, recipientId))) {
            throw new BusinessException("被照护人不存在");
        }
        Long chatWindowId = message.getChatWindowId();
        // 如果没有聊天窗口ID
        if (Objects.isNull(chatWindowId)) {
            // 查询聊天窗口
            chatWindowId = queryOrCreateUserChatWindow(userId, recipientId);
        }
        UserChatMessage userChatMessage = new UserChatMessage();
        userChatMessage.setChatWindowId(chatWindowId);
        userChatMessage.setSenderId(userId);
        userChatMessage.setMessageType(message.getMessageType().getCode());
        userChatMessage.setContent(message.getContent());
        return userChatMessageDao.insertChatMessage(userChatMessage) > NumberConstants.ZERO;
    }

    /**
     * 创建聊天窗口
     *
     * @param userId
     * @param recipientId
     * @return
     */
    private Long queryOrCreateUserChatWindow(Long userId, Long recipientId) {
        // 查询聊天窗口
        Long chatWindowId = userChatWindowInfoDao.findUserChatWindowIdByUserAndRecipient(userId, recipientId);
        // 如果不存在就创建
        if (Objects.nonNull(chatWindowId)) {
            return chatWindowId;
        }
        UserChatWindowInfo userChatWindowInfo = new UserChatWindowInfo();
        userChatWindowInfo.setUserId(userId);
        userChatWindowInfo.setRecipientId(recipientId);
        userChatWindowInfo.setDelFlag(NumberConstants.ZERO);
        try {
            boolean success = userChatWindowInfoDao.insertUserChatWindowInfo(userChatWindowInfo) == ONE;
            if (success && Objects.nonNull(userChatWindowInfo.getChatWindowId())) {
                return userChatWindowInfo.getChatWindowId();
            }
            throw new BusinessException("发送消息失败");
        } catch (DuplicateKeyException e) {
            // 如果抛出唯一ID重复的异常
            log.error("发送消息异常", e);
            return userChatWindowInfoDao.findUserChatWindowIdByUserAndRecipient(userId, recipientId);
        } catch (Exception e) {
            log.error("发送消息异常", e);
            throw new BusinessException("发送消息失败");
        }
    }

    @Override
    public Boolean clearMessage(Long chatWindowId) {
        if (Objects.isNull(chatWindowId)) {
            throw new BusinessException("聊天窗口ID不能为空");
        }
        try {
            Long userId = UserInfoUtils.getUserId();
            List<Long> messageIds = userChatMessageDao.selectChatMessagesIdByWindowId(chatWindowId);
            ListUtils.partition(messageIds, NumberConstants.THOUSAND).forEach(messageIdsPartition -> {
                userChatMessageDao.deleteChatMessageByIds(messageIdsPartition, userId);
            });
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("清空消息异常", e);
            throw new BusinessException("清空消息失败");
        }
    }

    @Override
    public Boolean readMessage(ReadMessageParam param) {
        if (Objects.isNull(param.getMaxMessageId())) {
            throw new BusinessException("消息ID不能为空");
        }
        if (Objects.isNull(param.getChatWindowId())) {
            throw new BusinessException("聊天窗口ID不能为空");
        }
        UserChatMessageReadRecord record = new UserChatMessageReadRecord();
        record.setUserId(UserInfoUtils.getUserId());
        record.setChatWindowId(param.getChatWindowId());
        record.setMaxReadMessageId(param.getMaxMessageId());
        // 创建或跟新已读记录
        return userChatMessageReadRecordDao.insertUserChatMessageReadRecordIfNotExist(record) > ZERO;
    }

    @Override
    public Boolean deleteMessage(List<Long> messageIds) {
        if (CollectionUtils.isEmpty(messageIds)) {
            throw new BusinessException("请选择要删除的消息");
        }
        Long userId = UserInfoUtils.getUserId();
        return userChatMessageDao.deleteChatMessageByIds(messageIds, userId) > ZERO;
    }
}
